#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <windows.h> 


#include "commdef.h"
#include "msgcore.h"

#include "pipe_server.h"




 
VOID pipe_InstanceThread(LPVOID); 





static ST_pipe_pool			gst_pipe_pool[MAX_THREAD] = { 0 };
static CRITICAL_SECTION		query_critical;



VOID	MyErrExit(LPSTR sz)
{
	printf("Error = %s\r\n",sz);
	ExitProcess(1);
	return;
}

const WCHAR	lpszPipename[] = {dflpszPipename}; 
const CHAR	szOverThread[]={"no more thread to reivce msg"}	;




void pipe_init(void)
{
	DWORD	i;
	DWORD	dwThreadID  ;
	TCHAR	wsEventName[64] = { 0 };

	ZeroMemory(&gst_pipe_pool[0],sizeof(gst_pipe_pool));

	for (i=0;i<MAX_THREAD;++i)
	{
		dwThreadID = 0 ;

		gst_pipe_pool[i].dwindex = i ;

		wsprintf(wsEventName,TEXT("PipeEvent%u"),i);

		gst_pipe_pool[i].hEvent = CreateEventW(NULL,TRUE,FALSE,wsEventName);
		
		ResetEvent(gst_pipe_pool[i].hEvent);

		gst_pipe_pool[i].hThread = CreateThread( 
				NULL,              // no security attribute 
				0,                 // default stack size 
				(LPTHREAD_START_ROUTINE) pipe_InstanceThread, 
				(LPVOID) i,    // thread parameter 
				0,                 // not suspended 
				&dwThreadID);      // returns thread ID 

		gst_pipe_pool[i].dwthreadid  = dwThreadID;
		
	}

	return;
}

int pipe_query(void)
{	
	int i ;

	for (i=0;i<MAX_THREAD;++i)
	{
		if (FALSE == gst_pipe_pool[i].bInUse )
		{
			return i;
		}
	}

	return -1;
}

unsigned int  pipe_use(int index,HANDLE pipehandle)
{
	gst_pipe_pool[index].bInUse = TRUE ;

	gst_pipe_pool[index].hpipe = pipehandle ;

	SetEvent(gst_pipe_pool[index].hEvent);

	Sleep(100);

	return gst_pipe_pool[index].dwThreadError;
}


void pipe_close(int index)
{	

	ResetEvent(gst_pipe_pool[index].hEvent);

	FlushFileBuffers(gst_pipe_pool[index].hpipe); 
	
	DisconnectNamedPipe(gst_pipe_pool[index].hpipe); 
	
	CloseHandle(gst_pipe_pool[index].hpipe); 

	gst_pipe_pool[index].hpipe = INVALID_HANDLE_VALUE;
	
	gst_pipe_pool[index].bInUse = FALSE;
	
	return;
}

static df_GetAnswerToRequest_Thread g_GetAnswerToRequest = NULL ;

DWORD WINAPI Pipe_main(UINT32 PIPE_TIMEOUT ,df_GetAnswerToRequest_Thread pthread)
{ 
	BOOL	fConnected = 0; 
	DWORD	dwThreadId =0; 
	HANDLE	hPipe=NULL, hThread = NULL; 
	
	
	int		pipefreeindex = 0 ;

	DWORD	dwthreaderror = 0 ;

	BOOL	bWait = TRUE;

	DWORD	cbWritten = 0 ;

	pipe_init();

	g_GetAnswerToRequest = 	pthread ;
	//licen
	while(bWait)
	{ 
		hPipe = CreateNamedPipeW
					( 
					lpszPipename,             // pipe name 
					PIPE_ACCESS_DUPLEX,       // read/write access 
					PIPE_TYPE_MESSAGE |       // message type pipe 
					PIPE_READMODE_MESSAGE |   // message-read mode 
					PIPE_WAIT,                // blocking mode 
					PIPE_UNLIMITED_INSTANCES, // max. instances  
					BUFSIZE,                  // output buffer size 
					BUFSIZE,                  // input buffer size 
					PIPE_TIMEOUT,             // client time-out 
					NULL);                    // no security attribute 

		if (hPipe == INVALID_HANDLE_VALUE) 
		{
			MyErrExit("CreatePipe"); 
		}
			
		printf("CreateNamedPipeed\r\n");
		// Wait for the client to connect; if it succeeds, 
		// the function returns a nonzero value. If the function returns 
		// zero, GetLastError returns ERROR_PIPE_CONNECTED. 

		fConnected = ConnectNamedPipe(hPipe, NULL) ?  TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); 
		
		printf("Pipe connected...\r\n!");

		if (fConnected) 
		{ 
			pipefreeindex = pipe_query() ;

			if ( INVALID_VALUE != pipefreeindex )
			{
				dwthreaderror = pipe_use(pipefreeindex,hPipe);
			}

			else
			{
				// The thread is max, could not connect, so close the pipe. 
				WriteFile( 
					hPipe,        // handle to pipe 
					szOverThread,      // buffer to write from 
					sizeof(szOverThread), // number of bytes to write 
					&cbWritten,   // number of bytes written 
					NULL);        // not overlapped I/O 
				CloseHandle(hPipe); 
			}

		} 
		else 
		{	
			// The client could not connect, so close the pipe. 
			CloseHandle(hPipe); 
		}
	}//end while

	return 1; 
} 


DWORD Pipe_close(void)
{
	return 0;
}

const BYTE hellomsg[]={"hello"};
const BYTE byemsg[]={"bye"};
const BYTE bOK[4] = {'O','K',0x00,0x00};


 
VOID pipe_InstanceThread(LPVOID lpvParam) 
{ 
	CHAR	chRequest[BUFSIZE] = {0}; 
	DWORD	cbBytesRead = 0 ;

	CHAR	chResponse[BUFSIZE] = {0}; 
	DWORD	cbSend = 0 ;	
	DWORD	cbResponWritten = 0; 

	BOOL	fSuccess = 0 ; 
	HANDLE	hPipe = NULL; 
	DWORD	n= 0 ;
	DWORD	nIndex = 0 ;

	BOOL	bWorkThread_Flag = TRUE ;

	ST_AUTH_TOKEN	stautoken  = { 0 };

	BYTE	bin[BUFSIZE];
	BYTE	bout[BUFSIZE];
	UINT	nbinretszie  ;
	UINT	noutretsize;
	// The thread's parameter is a handle to a pipe instance. 
	
	nIndex = (DWORD)(lpvParam );
	
	printf("create thread is ok, threadid is  %u\r\n",gst_pipe_pool[nIndex].dwthreadid);
	
	
	
	while (bWorkThread_Flag) 
	{ 
		//wait for pipe-client connect ....
		WaitForSingleObject(gst_pipe_pool[nIndex].hEvent,INFINITE);
		
		//
		
		hPipe = gst_pipe_pool[nIndex].hpipe ;
		// Read client requests from the pipe. 
		fSuccess = ReadFile( 
					hPipe,        // handle to pipe 
					chRequest,    // buffer to receive data 
					BUFSIZE,      // size of buffer 
					&cbBytesRead, // number of bytes read 
					NULL);        // not overlapped I/O 

		if (! fSuccess || cbBytesRead == 0) 
		{
			break; 
		}
		
			
		if (0 == memcmp(chRequest,hellomsg,sizeof(hellomsg)) )
		{
			memcpy(&chResponse[0],&bOK[0],sizeof(bOK));
			cbSend = sizeof(bOK);

			auth_genkey(&stautoken);

			memcpy(&chResponse[cbSend],&stautoken,sizeof(stautoken));
			cbSend += sizeof(stautoken);
		
		}
		else if (0 == memcmp(chRequest,byemsg,sizeof(byemsg)))
		{
			memcpy(chResponse,bOK,sizeof(bOK));
			cbSend = sizeof(bOK);
			pipe_close(nIndex);
		}
		else
		{
			paser_sendrequest(&chRequest[0],cbBytesRead,&bin[0],sizeof(bin),&nbinretszie);

			g_GetAnswerToRequest(&bin[0],nbinretszie,bout,sizeof(bout),&noutretsize);

			cbSend = build_sendrequest(&stautoken,bout,noutretsize,chResponse,sizeof(chResponse));
		}

			
		

		// Write the reply to the pipe. 
		fSuccess = WriteFile( 
					hPipe,        // handle to pipe 
					chResponse,      // buffer to write from 
					cbSend, // number of bytes to write 
					&cbResponWritten,   // number of bytes written 
					NULL);        // not overlapped I/O 

		if (! fSuccess || cbSend != cbResponWritten )
		{
			pipe_close(nIndex);
			//break; 
		}

	} //end while

	// Flush the pipe to allow the client to read the pipe's contents 
	// before disconnecting. Then disconnect the pipe, and close the 
	// handle to this pipe instance. 

	/*
	FlushFileBuffers(hPipe); 

	DisconnectNamedPipe(hPipe); 

	CloseHandle(hPipe); 
	*/
} 


